#pragma once

#include <nanobdd/nanobdd.h>

#include <bits/stdc++.h>
#include <execution>

namespace nexus {

class HeaderSpace : public nanobdd::Bdd {
 public:
  HeaderSpace() : nanobdd::Bdd() {}

  HeaderSpace(nanobdd::Bdd bdd) {
    root_ = bdd.root();
  }

  static HeaderSpace
  hsAll() {
    return nanobdd::bddTrue();
  }

  static HeaderSpace
  hsEmpty() {
    return nanobdd::bddFalse();
  }

  static HeaderSpace
  fromInt(std::bitset<32>& bits, int prefixLength) {
    nanobdd::Bdd result = nanobdd::bddTrue();
    // std::bitset<32> bits(addr);

    std::vector<nanobdd::Bdd> bdds;
    for (int i = 31; i > (31 - prefixLength); i--) {
      if (bits.test(i)) {
        bdds.push_back(nanobdd::getVar(31 - i));
      } else {
        bdds.push_back(nanobdd::getNvar(31 - i));
      }
    }

    return std::reduce(
        std::execution::par_unseq,
        bdds.begin(),
        bdds.end(),
        result,
        [](auto x, auto y) { return x & y; });
  }
};

} // namespace nexus